package com.controller;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.StringConverter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * 控制器层祖先类
 * ①将该类定义为一个抽象类,要求controller层中的其它Servlet都要继承该类
 * ②当采用BeanUtils把请求参数封装到javabean对象时,为了方便自行控制类型的转换,故实现Converter接口
 */
@SuppressWarnings("serial")
public abstract class AncestorServlet extends HttpServlet implements Converter
{
	
	
	
	@Override
	public final <T> T convert(Class<T> type, Object value)  //type表示“目标类型（希望转换成什么类型）”,value表示要被用来转换的原始数据
	{
		if(type == String.class && value != null && value.toString().trim().length() == 0)
		{
			return null;
		}
		return new StringConverter().convert(type, value);
	}
	
	
	
	
	
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		this.doPost(request, response);
	}
	
	
	
	
	
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		request.setCharacterEncoding("utf-8");
		String requestURI = request.getRequestURI();  //获取请求uri地址
		String substr = requestURI.substring(requestURI.lastIndexOf("/")+1);  //从请求uri地址中截取出最后的字符串
		System.err.println("即将调用函数："+substr);
		Method[] methods = this.getClass().getDeclaredMethods();  //反射出所有方法
		boolean bool = false;
		for(int i=0; i<methods.length; i++)
		{
			if(methods[i].getName().equals(substr))  //判断每一个方法的名称是否等于指定字符串
			{
				bool = true;
				Parameter[] parameters = methods[i].getParameters();  //反射出当前方法的全部参数
				Object[] args = new Object[parameters.length];
				for(int j=0; j<parameters.length; j++)
				{
					if(parameters[j].getType().isAssignableFrom(request.getClass()))  //判断参数的类型是否是Request类型
					{
						args[j] = request;
					}
					else if(parameters[j].getType().isAssignableFrom(response.getClass()))  //判断参数的类型是否是Responset类型
					{
						args[j] = response;
					}
					else if(parameters[j].getType().isAssignableFrom(request.getSession().getClass()))  //判断参数的类型是否是Session类型
					{
						args[j] = request.getSession();
					}
					else if(Map.class.isAssignableFrom(parameters[j].getType()))  //判断参数的类型是否是Map类型
					{
						args[j] = new LinkedHashMap<String, Object>();
					}
					//else if(parameters[j].getType().getPackage().getName().startsWith("com.bean"))  //判断参数的类型的包名是否为com.bean包中的类
					else
					{
						try
						{
							Object bean = parameters[j].getType().newInstance();  //创建bean对象
							Map<String,String[]> parameterMap = request.getParameterMap();
							ConvertUtils.register(this, String.class);  //注册转换器
							BeanUtils.populate(bean, parameterMap);  //将请求参数封装到bean对象中
							ConvertUtils.deregister();  //移除已注册的转换器
							args[j] = bean;
						}
						catch(Exception e)
						{
							throw new RuntimeException(String.format("无法创建%1$s对象或把请求参数封装到%1$s对象的过程中出错", parameters[j].getType().getSimpleName()), e);
						}
					}
				}
				try
				{
					Object obj = methods[i].invoke(this, args);
					if(obj != null)
					{
						if(obj instanceof String && ((String)obj).matches("[f|r]:.*"))
						{
							String result = (String)obj;
							String url = result.substring(2);  //把字符串开头的字符（f:或r:）移除
							if(result.startsWith("f:"))  //请求转发
							{
								this.forward(url, request, response);
								return;
							}
							if(result.startsWith("r:"))  //请求重定向
							{
								this.redirect(url, request, response);
								return;
							}
						}
						this.respondJson(obj, response);  //响应json数据
					}
				}
				catch(Exception e)
				{
					throw new RuntimeException(String.format("方法%s在运行过程中出错", methods[i]), e);
				}
				return;
			}
		}
		if(bool == false)
		{
			throw new RuntimeException(String.format("您要调用的%s(......)方法不存在", substr));
		}
	}
	
	
	
	
	
	/**
	 * 请求转发
	 */
	private void forward(String url, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		request.getRequestDispatcher(url).forward(request, response);
	}
	
	
	
	/**
	 * 请求重定向
	 */
	private void redirect(String url, HttpServletRequest request, HttpServletResponse response) throws IOException
	{
		response.sendRedirect(request.getContextPath() + url);
	}
	
	
	
	/**
	 * 响应json数据
	 */
	private void respondJson(Object data, HttpServletResponse response) throws IOException
	{
		Gson gson = new GsonBuilder().setPrettyPrinting().create();  //创建一个具有漂亮格式的Gson对象
		String json = gson.toJson(data);  //将对象序列化为json字符串
		response.setCharacterEncoding("utf-8");
		response.setContentType("application/json;charset=utf-8");
		response.getWriter().write(json);
	}
	
	
	
	
	
}